package org.yylnb.openplatform.gateway.filter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import org.yylnb.openplatform.commons.constans.ApiTagInRedis;
import org.yylnb.openplatform.commons.utlis.CommonsResult;
import org.yylnb.openplatform.gateway.api.CacheService;
import org.yylnb.openplatform.gateway.utils.LocalCacheUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.Map;

/**
 * @author RainLin
 * @date 2020/7/24 - 13:30
 */
@Component
public class RoutingFilter extends ZuulFilter {
    private static final Logger LOGGER = LoggerFactory.getLogger(RoutingFilter.class);

    private final ObjectMapper objectMapper;

    private final CacheService cacheService;

    public RoutingFilter(ObjectMapper objectMapper, CacheService cacheService) {
        this.objectMapper = objectMapper;
        this.cacheService = cacheService;
    }

    @Override
    public String filterType() {
        //前置过滤器
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 100;
    }

    @Override
    public boolean shouldFilter() {
        //获取上下文
        RequestContext context = RequestContext.getCurrentContext();
        //因为在前面还有其他的过滤器 可能会拦截请求,所以在出现拦截的情况下,这个过滤器应当不启用
        return context.sendZuulResponse();
    }

    @Override
    public Object run() throws ZuulException {
        //首先要获取请求对象
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();

        //获取method参数
        String method = request.getParameter("method");
        LOGGER.error("收到的请求的服务的标识为:{}", method);

        //因为前面的过滤器已经查询并且保存了一份,所以这个地方直接获取就可以了
        Map<String, String> apiRoutingMap = LocalCacheUtils.getMapping(ApiTagInRedis.API_MAPPING + method);

        //如果没有获取到的处理方法
        if (apiRoutingMap == null || apiRoutingMap.size() == 0) {
            //用户传递的method可能是错误的值,没有找到对应的服务
            context.setSendZuulResponse(false);
            HttpServletResponse response = context.getResponse();
            response.setContentType("application/json;charset=utf-8");
            try {
                context.setResponseBody(objectMapper.writeValueAsString(CommonsResult.ERROR.msg("未知的method")));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return null;
        }

        //如果获取到结果
        // 服务的id
        String serviceId = apiRoutingMap.get("serviceId");
        //服务的请求路径
        String insideApiUrl = apiRoutingMap.get("insideApiUrl");
        context.put(FilterConstants.SERVICE_ID_KEY, serviceId);

        //获取到请求中查询参数的所有的参数名
        Enumeration<String> parameterNames = request.getParameterNames();
        //遍历所有参数
        while (parameterNames.hasMoreElements()) {
            //获取到每一个变量名,就是 name  age password 等等
            String paramName = parameterNames.nextElement();
            //获取当前参数对应的具体的值,用于替换掉占位符
            String value = request.getParameter(paramName);
            //用真正的结果替换掉占位符
            insideApiUrl = insideApiUrl.replace("{" + paramName + "}", value);
        }

        context.put(FilterConstants.REQUEST_URI_KEY, insideApiUrl);


        return null;
    }
}



